home *** CD-ROM | disk | FTP | other *** search
/ Aminet 43 / Aminet 43 (2001)(GTI - Schatztruhe)[!][Jun 2001].iso / Aminet / comm / mail / YAM22src.lha / YAM_FO.c < prev    next >
C/C++ Source or Header  |  2000-11-03  |  31KB  |  849 lines

  1. /***************************************************************************
  2.  
  3.  YAM - Yet Another Mailer
  4.  Copyright (C) 2000  Marcel Beck <mbeck@yam.ch>
  5.  
  6.  This program is free software; you can redistribute it and/or modify
  7.  it under the terms of the GNU General Public License as published by
  8.  the Free Software Foundation; either version 2 of the License, or
  9.  (at your option) any later version.
  10.  
  11.  This program is distributed in the hope that it will be useful,
  12.  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  GNU General Public License for more details.
  15.  
  16.  You should have received a copy of the GNU General Public License
  17.  along with this program; if not, write to the Free Software
  18.  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  
  20.  YAM Official Support Site :  http://www.yam.ch
  21.  YAM OpenSource project    :  http://sourceforge.net/projects/yamos/
  22.  
  23. ***************************************************************************/
  24.  
  25. #include "YAM.h"
  26.  
  27. /***************************************************************************
  28.  Module: Folder Configuration
  29. ***************************************************************************/
  30.  
  31. /// FO_CreateList
  32. //  Creates a linked list of all folders
  33. struct Folder **FO_CreateList(void)
  34. {
  35.    int max, i;
  36.    struct Folder **flist;
  37.    APTR lv = G->MA->GUI.NL_FOLDERS;
  38.  
  39.    get(lv, MUIA_NList_Entries, &max);
  40.    if (flist = calloc(max+1, sizeof(struct Folder *)))
  41.    {
  42.       flist[0] = (struct Folder *)max;
  43.       for (i = 0; i < max; i++) DoMethod(lv, MUIM_NList_GetEntry, i, &flist[i+1]);
  44.    }
  45.    return flist;
  46. }
  47. ///
  48. /// FO_GetCurrentFolder
  49. //  Returns pointer to active folder
  50. struct Folder *FO_GetCurrentFolder(void)
  51. {
  52.    struct Folder *fo;
  53.    DoMethod(G->MA->GUI.NL_FOLDERS, MUIM_NList_GetEntry, MUIV_NList_GetEntry_Active, &fo);
  54.    return fo;
  55. }
  56. ///
  57. /// FO_GetFolderRexx
  58. //  Finds a folder by its name, type or position
  59. struct Folder *FO_GetFolderRexx(char *arg, int *pos)
  60. {
  61.    int i, nr = 0;
  62.    struct Folder *fo = NULL, **flist;
  63.    char *p = arg;
  64.    BOOL numeric = TRUE;
  65.  
  66.    if (flist = FO_CreateList())
  67.    {
  68.       while (*p) if (!isdigit((int)*p++)) numeric = FALSE;
  69.       if (numeric) if ((i = atoi(arg)) >= 0 && i < (int)*flist) if (flist[++i]->Type != FT_SEPARATOR) nr = i;
  70.       if (!nr) for (i = 1; i <= (int)*flist; i++)
  71.          if ((!Stricmp(arg, flist[i]->Name) && flist[i]->Type != FT_SEPARATOR) ||
  72.              (!stricmp(arg, "incoming")     && flist[i]->Type == FT_INCOMING) ||
  73.              (!stricmp(arg, "outgoing")     && flist[i]->Type == FT_OUTGOING) ||
  74.              (!stricmp(arg, "sent")         && flist[i]->Type == FT_SENT) ||
  75.              (!stricmp(arg, "deleted")      && flist[i]->Type == FT_DELETED)) { nr = i; break; }
  76.       if (nr)
  77.       {
  78.          fo = flist[nr];
  79.          if (pos) *pos = --nr;
  80.       }
  81.       free(flist);
  82.    }
  83.    return fo;
  84. }
  85. ///
  86. /// FO_GetFolderByName
  87. //  Finds a folder by its name
  88. struct Folder *FO_GetFolderByName(char *name, int *pos)
  89. {
  90.    int i;
  91.    struct Folder *fo = NULL;
  92.  
  93.    for (i = 0;; i++)
  94.    {
  95.       DoMethod(G->MA->GUI.NL_FOLDERS, MUIM_NList_GetEntry, i, &fo);
  96.       if (!fo) break;
  97.       if (!strcmp(fo->Name, name) && fo->Type != FT_SEPARATOR) break;
  98.    }
  99.    if (pos) *pos = i;
  100.    return fo;
  101. }
  102. ///
  103. /// FO_GetFolderByType
  104. //  Finds a folder by its name
  105. struct Folder *FO_GetFolderByType(int type, int *pos)
  106. {
  107.    int i;
  108.    struct Folder *fo = NULL;
  109.  
  110.    for (i = 0;; i++)
  111.    {
  112.       DoMethod(G->MA->GUI.NL_FOLDERS, MUIM_NList_GetEntry, i, &fo);
  113.       if (!fo) break;
  114.       if (fo->Type == type) break;
  115.    }
  116.    if (fo && pos) *pos = i;
  117.    return fo;
  118. }
  119. ///
  120. /// FO_GetFolderPosition
  121. //  Gets the position of a folder in the list
  122. int FO_GetFolderPosition(struct Folder *findfo)
  123. {
  124.    int i;
  125.    struct Folder *fo = NULL;
  126.  
  127.    for (i = 0;; i++)
  128.    {
  129.       DoMethod(G->MA->GUI.NL_FOLDERS, MUIM_NList_GetEntry, i, &fo);
  130.       if (!fo) return -1;
  131.       if (fo == findfo) return i;
  132.    }
  133. }
  134. ///
  135. /// FO_LoadConfig
  136. //  Loads folder configuration from .fconfig file
  137. BOOL FO_LoadConfig(struct Folder *fo)
  138. {
  139.    BOOL success = FALSE;
  140.    FILE *fh;
  141.    char buffer[SIZE_LARGE], fname[SIZE_PATHFILE];
  142.  
  143.    strmfp(fname, GetFolderDir(fo), ".fconfig");
  144.    if (fh = fopen(fname, "r"))
  145.    {
  146.       fgets(buffer, SIZE_LARGE, fh);
  147.       if (!strnicmp(buffer, "YFC", 3))
  148.       {
  149.          while (fgets(buffer, SIZE_LARGE, fh))
  150.          {
  151.             char *p, *value;
  152.             if (value = strchr(buffer, '=')) for (++value; ISpace(*value); value++);
  153.             if (p = strpbrk(buffer,"\r\n")) *p = 0;
  154.             for (p = buffer; *p && !ISpace(*p); p++); *p = 0;
  155.             if (*buffer && value)
  156.             {
  157.                if (!stricmp(buffer, "Name"))     stccpy(fo->Name, value, SIZE_NAME);
  158.                if (!stricmp(buffer, "MaxAge"))   fo->MaxAge = atoi(value);
  159.                if (!stricmp(buffer, "Password")) stccpy(fo->Password, Decrypt(value), SIZE_PASSWORD);
  160.                if (!stricmp(buffer, "Type"))     fo->Type = atoi(value);
  161.                if (!stricmp(buffer, "XPKType"))  fo->XPKType = atoi(value);
  162.                if (!stricmp(buffer, "Sort1"))    fo->Sort[0] = atoi(value);
  163.                if (!stricmp(buffer, "Sort2"))    fo->Sort[1] = atoi(value);
  164.                if (!stricmp(buffer, "MLAddress"))stccpy(fo->MLAddress, value, SIZE_ADDRESS);
  165.                if (!stricmp(buffer, "MLPattern"))stccpy(fo->MLPattern, value, SIZE_PATTERN);
  166.             }
  167.          }
  168.          success = TRUE;
  169.       }
  170.       fclose(fh);
  171.    }
  172.    return success;
  173. }
  174. ///
  175. /// FO_SaveConfig
  176. //  Saves folder configuration to .fconfig file
  177. void FO_SaveConfig(struct Folder *fo)
  178. {
  179.    struct DateStamp ds;
  180.    char fname[SIZE_PATHFILE];
  181.    FILE *fh;
  182.  
  183.    strmfp(fname, GetFolderDir(fo), ".fconfig");
  184.    if (fh = fopen(fname, "w"))
  185.    {
  186.       fprintf(fh, "YFC1 - YAM Folder Configuration\n");
  187.       fprintf(fh, "Name        = %s\n", fo->Name);
  188.       fprintf(fh, "MaxAge      = %ld\n", fo->MaxAge);
  189.       fprintf(fh, "Password    = %s\n", Encrypt(fo->Password));
  190.       fprintf(fh, "Type        = %ld\n", fo->Type);
  191.       fprintf(fh, "XPKType     = %ld\n", fo->XPKType);
  192.       fprintf(fh, "Sort1       = %ld\n", fo->Sort[0]);
  193.       fprintf(fh, "Sort2       = %ld\n", fo->Sort[1]);
  194.       fprintf(fh, "MLPattern   = %s\n", fo->MLPattern);
  195.       fprintf(fh, "MLAddress   = %s\n", fo->MLAddress);
  196.       fclose(fh);
  197.       strmfp(fname, GetFolderDir(fo), ".index");
  198.       if (!(fo->Flags&FOFL_MODIFY)) SetFileDate(fname, DateStamp(&ds));
  199.    }
  200.    else ER_NewError(GetStr(MSG_ER_CantCreateFile), fname, NULL);
  201. }
  202. ///
  203. /// FO_NewFolder
  204. //  Initializes a new folder and creates its directory
  205. struct Folder *FO_NewFolder(int type, char *path, char *name)
  206. {
  207.    struct Folder *folder = calloc(1, sizeof(struct Folder));
  208.    folder->Sort[0] = 1;
  209.    folder->Sort[1] = 3;
  210.    folder->Type = type;
  211.    stccpy(folder->Path, path, SIZE_PATH);
  212.    stccpy(folder->Name, name, SIZE_NAME);
  213.    if (CreateDirectory(GetFolderDir(folder))) return folder;
  214.    free(folder);
  215.    return NULL;
  216. }
  217. ///
  218. /// FO_CreateFolder
  219. //  Adds a new entry to the folder list
  220. BOOL FO_CreateFolder(int type, char *path, char *name)
  221. {
  222.    struct Folder *folder = FO_NewFolder(type, path, name);
  223.    if (folder)
  224.    {
  225.       DoMethod(G->MA->GUI.NL_FOLDERS, MUIM_NList_InsertSingle, folder, MUIV_NList_Insert_Bottom);
  226.       FO_SaveConfig(folder);
  227.       free(folder);
  228.       return TRUE;
  229.    }
  230.    return FALSE;
  231. }
  232. ///
  233. /// FO_LoadTree
  234. //  Loads folder list from a file
  235. BOOL FO_LoadTree(char *fname)
  236. {
  237.    static struct Folder fo;
  238.    BOOL success = FALSE;
  239.    char buffer[SIZE_LARGE];
  240.    int nested = 0, i = 0;
  241.    FILE *fh;
  242.    APTR lv = G->MA->GUI.NL_FOLDERS;
  243.    
  244.    if (fh = fopen(fname, "r"))
  245.    {
  246.       GetLine(fh, buffer, SIZE_LARGE);
  247.       if (!strncmp(buffer, "YFO", 3))
  248.       {
  249.          DoMethod(lv, MUIM_NList_Clear);
  250.          set(lv, MUIA_NList_Quiet, TRUE);
  251.          while (GetLine(fh, buffer, SIZE_LARGE))
  252.          {
  253.             clear(&fo, sizeof(struct Folder));
  254.             if (!strncmp(buffer, "@FOLDER", 7))
  255.             {
  256.                fo.Type = FT_CUSTOM;
  257.                fo.Sort[0] = 1; fo.Sort[1] = 3;
  258.                stccpy(fo.Name, Trim(&buffer[8]),SIZE_NAME);
  259.                stccpy(fo.Path, Trim(GetLine(fh, buffer, SIZE_LARGE)), SIZE_PATH);
  260.                if (CreateDirectory(GetFolderDir(&fo)))
  261.                {
  262.                   if (!FO_LoadConfig(&fo))
  263.                   {
  264.                      if (!stricmp(FilePart(fo.Path), FolderNames[0])) fo.Type = FT_INCOMING;
  265.                      if (!stricmp(FilePart(fo.Path), FolderNames[1])) fo.Type = FT_OUTGOING;
  266.                      if (!stricmp(FilePart(fo.Path), FolderNames[2])) fo.Type = FT_SENT;
  267.                      if (!stricmp(FilePart(fo.Path), FolderNames[3])) fo.Type = FT_DELETED;
  268.                      FO_SaveConfig(&fo);
  269.                   }
  270.                   fo.SortIndex = i++;
  271.                   DoMethod(lv, MUIM_NList_InsertSingle, &fo, MUIV_NList_Insert_Bottom);
  272.                }
  273.                do if (!strcmp(buffer, "@ENDFOLDER")) break;
  274.                while (GetLine(fh, buffer, SIZE_LARGE));
  275.             }
  276.             else if (!strncmp(buffer, "@SEPARATOR", 10))
  277.             {
  278.                fo.Type = FT_SEPARATOR;
  279.                stccpy(fo.Name, Trim(&buffer[11]), SIZE_NAME);
  280.                do if (!strcmp(buffer, "@ENDSEPARATOR")) break;
  281.                while (GetLine(fh, buffer, SIZE_LARGE));
  282.                fo.SortIndex = i++;
  283.                DoMethod(lv, MUIM_NList_InsertSingle, &fo, MUIV_NList_Insert_Bottom);
  284.             }
  285.             else if (!strncmp(buffer, "@GROUP", 6))  /* not yet implemented */
  286.             {
  287.                fo.Type = FT_GROUP;
  288.                stccpy(fo.Name, Trim(&buffer[7]), SIZE_NAME);
  289.                nested++;
  290.             }
  291.             else if (!strcmp(buffer,"@ENDGROUP"))
  292.             {
  293.                nested--;
  294.             }
  295.          }
  296.          set(lv, MUIA_NList_Quiet, FALSE);
  297.       }
  298.       fclose(fh);
  299.       success = TRUE;
  300.    }
  301.    return success;
  302. }
  303. ///
  304. /// FO_SaveTree
  305. //  Saves folder list to a file
  306. BOOL FO_SaveTree(char *fname)
  307. {
  308.    BOOL success = TRUE;
  309.    struct Folder *fo;
  310.    FILE *fh;
  311.    APTR lv = G->MA->GUI.NL_FOLDERS;
  312.    int i;
  313.  
  314.    if (fh = fopen(fname, "w"))
  315.    {
  316.       fputs("YFO1 - YAM Folders\n", fh);
  317.       for (i = 0;; i++)
  318.       {
  319.          DoMethod(lv, MUIM_NList_GetEntry, i, &fo);
  320.          if (!fo) break;
  321.          fo->SortIndex = i;
  322.          switch (fo->Type)
  323.          {
  324.             case FT_SEPARATOR:  fprintf(fh, "@SEPARATOR %s\n@ENDSEPARATOR\n", fo->Name);
  325.                                 break;
  326.             case FT_GROUP:      fprintf(fh, "@GROUP %s\n", fo->Name);   /* not yet implemented */
  327.                                 fputs("@ENDGROUP\n", fh);
  328.                                 break;
  329.             default:            fprintf(fh, "@FOLDER %s\n%s\n@ENDFOLDER\n", fo->Name, fo->Path);
  330.                                 break;
  331.          }
  332.       }
  333.       fclose(fh);
  334.       success = TRUE;
  335.    }
  336.    else ER_NewError(GetStr(MSG_ER_CantCreateFile), fname, NULL);
  337.    return success;
  338. }
  339. ///
  340. /// FO_XPKUpdateFolder
  341. //  Updates compression mode for a folder
  342. void FO_XPKUpdateFolder(struct Folder *fo, int oldtype)
  343. {
  344.    if (fo->XPKType != oldtype)
  345.    {
  346.       struct Mail *mail;
  347.       int i;
  348.       Busy(GetStr(MSG_BusyUncompressingFO), "", 0, fo->Total);
  349.       for (i = 0, mail = fo->Messages; mail; mail = mail->Next, i++)
  350.       {
  351.          Busy(NULL, NULL, i, 0);
  352.          RepackMailFile(mail, fo->XPKType, fo->Password);
  353.       }
  354.       BusyEnd;
  355.    }
  356. }
  357. ///
  358. /// FO_Move
  359. //  Moves a folder directory to a new destination
  360. BOOL FO_Move(char *srcbuf, char *dstbuf)
  361. {
  362.    if (!RenameFile(srcbuf, dstbuf)) if (!CopyFile(dstbuf, 0, srcbuf, 0)) return FALSE;
  363.    return TRUE;
  364. }
  365. ///
  366. /// FO_MoveFolderDir
  367. //  Moves a folder to a new directory
  368. BOOL FO_MoveFolderDir(struct Folder *fo, struct Folder *oldfo)
  369. {
  370.    struct Mail *mail;
  371.    char srcbuf[SIZE_PATHFILE], dstbuf[SIZE_PATHFILE];
  372.    BOOL success = TRUE;
  373.    int i;
  374.    Busy(GetStr(MSG_BusyMoving), itoa(fo->Total), 0, fo->Total);
  375.    strcpy(srcbuf, GetFolderDir(oldfo));
  376.    strcpy(dstbuf, GetFolderDir(fo));
  377.    for (i = 0, mail = fo->Messages; mail && success; mail = mail->Next, i++)
  378.    {
  379.       Busy(NULL, NULL, i, 0);
  380.       GetMailFile(dstbuf, fo, mail);
  381.       GetMailFile(srcbuf, oldfo, mail);
  382.       if (!FO_Move(srcbuf, dstbuf)) success = FALSE;
  383.       else RepackMailFile(mail, fo->XPKType, fo->Password);
  384.    }
  385.    if (success)
  386.    {
  387.       strmfp(srcbuf, GetFolderDir(oldfo), ".index");
  388.       strmfp(dstbuf, GetFolderDir(fo), ".index");
  389.       FO_Move(srcbuf, dstbuf);
  390.       DeleteMailDir(GetFolderDir(oldfo), FALSE);
  391.    }
  392.    BusyEnd;
  393.    return success;
  394. }
  395. ///
  396. /// FO_EnterPassword
  397. //  Sets password for a protected folder
  398. BOOL FO_EnterPassword(struct Folder *fo)
  399. {
  400.    char passwd[SIZE_PASSWORD], passwd2[SIZE_PASSWORD];
  401.  
  402.    for (*passwd = 0;;)
  403.    {
  404.       *passwd = *passwd2 = 0;
  405.       if (!StringRequest(passwd, SIZE_PASSWORD, GetStr(MSG_Folder), GetStr(MSG_CO_ChangeFolderPass), GetStr(MSG_Okay), NULL, GetStr(MSG_Cancel), TRUE, G->FO->GUI.WI)) return FALSE;
  406.       if (*passwd) if (!StringRequest(passwd2, SIZE_PASSWORD, GetStr(MSG_Folder), GetStr(MSG_CO_RetypePass), GetStr(MSG_Okay), NULL, GetStr(MSG_Cancel), TRUE, G->FO->GUI.WI)) return FALSE;
  407.       if (!Stricmp(passwd, passwd2)) break; else DisplayBeep(NULL);
  408.    }
  409.    if (!*passwd) return FALSE;
  410.    strcpy(fo->Password, passwd);
  411.    return TRUE;
  412. }
  413. ///
  414. /// FO_FoldernameRequest
  415. //  Asks user for a folder name and path
  416. BOOL FO_FoldernameRequest(char *string)
  417. {
  418.    char *path;
  419.    APTR bt_okay, bt_cancel, wi, st_pa, st_di;
  420.    int ret_code = -1;
  421.  
  422.    wi = WindowObject,
  423.       MUIA_Window_Title, GetStr(MSG_Folder),
  424.       MUIA_Window_RefWindow, G->MA->GUI.WI,
  425.       MUIA_Window_LeftEdge, MUIV_Window_LeftEdge_Centered,
  426.       MUIA_Window_TopEdge, MUIV_Window_TopEdge_Centered,
  427.       MUIA_Window_ID, MAKE_ID('N','F','R','Q'),
  428.       WindowContents, VGroup,
  429.          Child, VGroup,
  430.             GroupFrame,
  431.             MUIA_Background, MUII_GroupBack,
  432.             Child, LLabel(GetStr(MSG_CO_SelectDir)),
  433.             Child, ColGroup(2),
  434.                Child, Label2(GetStr(MSG_Path)),
  435.                Child, PopaslObject,
  436.                   MUIA_Popasl_Type, ASL_FileRequest,
  437.                   MUIA_Popstring_String, st_pa = MakeString(SIZE_PATH, ""),
  438.                   MUIA_Popstring_Button, PopButton(MUII_PopDrawer),
  439.                   ASLFR_DrawersOnly, TRUE,
  440.                End,
  441.                Child, Label2(GetStr(MSG_Directory)),
  442.                Child, st_di = MakeString(SIZE_FILE, ""),
  443.             End,
  444.          End,
  445.          Child, ColGroup(2),
  446.             Child, bt_okay = MakeButton(GetStr(MSG_Okay)),
  447.             Child, bt_cancel = MakeButton(GetStr(MSG_Cancel)),
  448.          End,
  449.       End,
  450.    End;
  451.    if (wi)
  452.    {
  453.       setstring(st_pa, G->MA_MailDir);
  454.       setstring(st_di, string);
  455.       set(st_di, MUIA_String_Reject, " \";:/#?(|)");
  456.       set(wi, MUIA_Window_ActiveObject, st_di);
  457.       set(G->App, MUIA_Application_Sleep, TRUE);
  458.       DoMethod(G->App, OM_ADDMEMBER, wi);
  459.       DoMethod(bt_okay  , MUIM_Notify, MUIA_Pressed, FALSE, G->App, 2, MUIM_Application_ReturnID, 1);
  460.       DoMethod(bt_cancel, MUIM_Notify, MUIA_Pressed, FALSE, G->App, 2, MUIM_Application_ReturnID, 3);
  461.       DoMethod(st_di, MUIM_Notify, MUIA_String_Acknowledge, MUIV_EveryTime, G->App, 2, MUIM_Application_ReturnID, 1);
  462.       DoMethod(wi, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, G->App, 2, MUIM_Application_ReturnID, 3);
  463.       if (!SafeOpenWindow(wi)) ret_code = 0;
  464.       while (ret_code == -1)
  465.       {
  466.          ULONG signals;
  467.          switch (DoMethod(G->App, MUIM_Application_Input, &signals))
  468.          {
  469.             case 1: if (*(GetMUIStringPtr(st_di))) ret_code = 1;
  470.                     break;
  471.             case 3: ret_code = 0; break;
  472.          }
  473.          if (ret_code == -1 && signals) Wait(signals);
  474.       }
  475.       path = GetMUIStringPtr(st_pa);
  476.       if (ret_code > 0)
  477.          if (!stricmp(path, G->MA_MailDir)) GetMUIString(string, st_di);
  478.          else strmfp(string, path, GetMUIStringPtr(st_di));
  479.       DoMethod(G->App, OM_REMMEMBER, wi);
  480.       set(G->App, MUIA_Application_Sleep, FALSE);
  481.    }
  482.    return (BOOL)ret_code;
  483. }
  484. ///
  485. /// FO_GetFolder
  486. //  Fills form with data from folder structure
  487. void FO_GetFolder(struct Folder *folder, BOOL existing)
  488. {
  489.    struct FO_GUIData *gui = &G->FO->GUI;
  490.    BOOL isdefault = (folder->Type != FT_CUSTOM && folder->Type != FT_CUSTOMSENT && folder->Type != FT_CUSTOMMIXED);
  491.    static int type2cycle[9] = { 0,0,1,1,2,-1,1,2,-1 };
  492.    int i;
  493.  
  494.    set(gui->ST_FNAME, MUIA_String_Contents, folder->Name);
  495.    set(gui->TX_FPATH, MUIA_Text_Contents, folder->Path);
  496.    set(gui->ST_MAXAGE, MUIA_String_Integer, folder->MaxAge);
  497.    set(gui->CY_FTYPE, MUIA_Cycle_Active, type2cycle[folder->Type]);
  498.    set(gui->CY_FMODE, MUIA_Cycle_Active, folder->XPKType);
  499.    for (i = 0; i < 2; i++)
  500.    {
  501.       set(gui->CY_SORT[i], MUIA_Cycle_Active, ABS(folder->Sort[i])-1);
  502.       set(gui->CH_REVERSE[i], MUIA_Selected, folder->Sort[i] < 0);
  503.    }
  504.    set(gui->ST_MLADDRESS, MUIA_String_Contents, folder->MLAddress);
  505.    set(gui->ST_MLPATTERN, MUIA_String_Contents, folder->MLPattern);
  506.    set(gui->CY_FTYPE, MUIA_Disabled, isdefault);
  507.    set(gui->CY_FMODE, MUIA_Disabled, isdefault || existing);
  508.    set(gui->BT_MOVE, MUIA_Disabled, existing);
  509. }
  510. ///
  511. /// FO_PutFolder
  512. //  Updates folder structure with form data
  513. void FO_PutFolder(struct Folder *folder)
  514. {
  515.    struct FO_GUIData *gui = &G->FO->GUI;
  516.    BOOL isdefault = (folder->Type != FT_CUSTOM && folder->Type != FT_CUSTOMSENT && folder->Type != FT_CUSTOMMIXED);
  517.    static int cycle2type[3] = { FT_CUSTOM,FT_CUSTOMSENT,FT_CUSTOMMIXED };
  518.    int i;
  519.  
  520.    GetMUIString(folder->Name, gui->ST_FNAME);
  521.    GetMUIText(folder->Path, gui->TX_FPATH);
  522.    folder->MaxAge = GetMUIInteger(gui->ST_MAXAGE);
  523.    if (!isdefault)
  524.    {
  525.       folder->Type = cycle2type[GetMUICycle(gui->CY_FTYPE)];
  526.       folder->XPKType = GetMUICycle(gui->CY_FMODE);
  527.    }
  528.    for (i = 0; i < 2; i++)
  529.    {
  530.       folder->Sort[i] = GetMUICycle(gui->CY_SORT[i])+1;
  531.       if (GetMUICheck(gui->CH_REVERSE[i])) folder->Sort[i] = -folder->Sort[i];
  532.    }
  533.    GetMUIString(folder->MLPattern, gui->ST_MLPATTERN);
  534.    GetMUIString(folder->MLAddress, gui->ST_MLADDRESS);
  535. }
  536. ///
  537. /// FO_NewSeparatorFunc
  538. //  Creates a new separator
  539. SAVEDS void FO_NewSeparatorFunc(void)
  540. {
  541.    struct Folder folder;
  542.    clear(&folder, sizeof(struct Folder));
  543.    folder.Type = FT_SEPARATOR;
  544.    if (StringRequest(folder.Name, SIZE_NAME, GetStr(MSG_MA_NewSeparator), GetStr(MSG_FO_NewSepReq), GetStr(MSG_Okay), NULL, GetStr(MSG_Cancel), FALSE, G->MA->GUI.WI))
  545.    {
  546.       int pos;
  547.       APTR lv = G->MA->GUI.NL_FOLDERS;
  548.       get(lv, MUIA_NList_Active, &pos);
  549.       DoMethod(lv, MUIM_NList_InsertSingle, &folder, ++pos);
  550.    }
  551. }
  552. MakeHook(FO_NewSeparatorHook, FO_NewSeparatorFunc);
  553. ///
  554. /// FO_NewFolderFunc
  555. //  Creates a new folder
  556. SAVEDS void FO_NewFolderFunc(void)
  557. {
  558.    int mode = MUI_Request(G->App, G->MA->GUI.WI, 0, GetStr(MSG_MA_NewFolder), GetStr(MSG_FO_NewFolderGads), GetStr(MSG_FO_NewFolderReq));
  559.    static struct Folder folder;
  560.  
  561.    clear(&folder, sizeof(struct Folder));
  562.    folder.Sort[0] = 1; folder.Sort[1] = 3; folder.Type = FT_CUSTOM;
  563.    switch (mode)
  564.    {
  565.       case 0: return;
  566.       case 1: if (!FO_FoldernameRequest(folder.Path)) return;
  567.               stccpy(folder.Name, FilePart(folder.Path), SIZE_NAME);
  568.               break;
  569.       case 2: memcpy(&folder, FO_GetCurrentFolder(), sizeof(struct Folder));
  570.               if (folder.Type == FT_SEPARATOR) { FO_NewSeparatorFunc(); return; }
  571.               else if (folder.Type == FT_INCOMING || folder.Type == FT_DELETED) folder.Type = FT_CUSTOM;
  572.               else if (folder.Type == FT_OUTGOING || folder.Type == FT_SENT) folder.Type = FT_CUSTOMSENT;
  573.               *folder.Path = 0;
  574.               if (!FO_FoldernameRequest(folder.Path)) return;
  575.               stccpy(folder.Name, FilePart(folder.Path), SIZE_NAME);
  576.               break;
  577.       case 3: if (!ReqFile(ASL_FOLDER, G->MA->GUI.WI, GetStr(MSG_FO_SelectDir), 4, G->MA_MailDir, "")) return;
  578.               stccpy(folder.Path, G->ASLReq[ASL_FOLDER]->fr_Drawer, SIZE_PATH);
  579.               FO_LoadConfig(&folder);
  580.               break;
  581.    }
  582.    if (!G->FO)
  583.    {
  584.       if (!(G->FO = FO_New())) return;
  585.       if (!SafeOpenWindow(G->FO->GUI.WI)) { DisposeModulePush(&G->FO); return; }
  586.    }
  587.    FO_GetFolder(&folder, mode==3);
  588. }
  589. MakeHook(FO_NewFolderHook, FO_NewFolderFunc);
  590. ///
  591. /// FO_EditFolderFunc
  592. //  Opens folder window to edit the settings of the active folder
  593. SAVEDS void FO_EditFolderFunc(void)
  594. {
  595.    struct Folder *folder = FO_GetCurrentFolder();
  596.    if (folder->Type == FT_SEPARATOR)
  597.    {
  598.       if (StringRequest(folder->Name, SIZE_NAME, GetStr(MSG_FO_EditFolder), GetStr(MSG_FO_NewSepReq), GetStr(MSG_Okay), NULL, GetStr(MSG_Cancel), FALSE, G->MA->GUI.WI))
  599.          DoMethod(G->MA->GUI.NL_FOLDERS, MUIM_NList_Redraw, MUIV_NList_Redraw_Active);
  600.    }
  601.    else
  602.    {
  603.       if (!G->FO)
  604.       {
  605.          if (!(G->FO = FO_New())) return;
  606.          if (!SafeOpenWindow(G->FO->GUI.WI)) { DisposeModulePush(&G->FO); return; }
  607.       }
  608.       FO_GetFolder(G->FO->EditFolder = folder, FALSE);
  609.    }
  610. }
  611. MakeHook(FO_EditFolderHook, FO_EditFolderFunc);
  612. ///
  613. /// FO_DeleteFolderFunc
  614. //  Removes the active folder
  615. SAVEDS void FO_DeleteFolderFunc(void)
  616. {
  617.    APTR lv = G->MA->GUI.NL_FOLDERS;
  618.    struct Folder *f, *folder = FO_GetCurrentFolder();
  619.    int i, pos, used = 0;
  620.    get(lv, MUIA_NList_Active, &pos);
  621.  
  622.    for (i = 0; ; i++)
  623.    {
  624.       DoMethod(lv, MUIM_NList_GetEntry, i, &f);
  625.       if (!f) break; else if (!stricmp(f->Path, folder->Path)) used++;
  626.    }
  627.    switch (folder->Type)
  628.    {
  629.       case FT_CUSTOM:
  630.       case FT_CUSTOMSENT:
  631.       case FT_CUSTOMMIXED: if (used < 2)
  632.                            {
  633.                               if (!MUI_Request(G->App, G->MA->GUI.WI, 0, NULL, GetStr(MSG_YesNoReq), GetStr(MSG_CO_ConfirmDelete))) return;
  634.                               DeleteMailDir(GetFolderDir(folder), FALSE);
  635.                            }
  636.                            ClearMailList(folder, TRUE);
  637.       case FT_SEPARATOR:   DoMethod(lv, MUIM_NList_Remove, pos);
  638.                            FO_SaveTree(CreateFilename(".folders"));
  639.                            break;
  640.       default:             break;
  641.    }
  642. }
  643. MakeHook(FO_DeleteFolderHook, FO_DeleteFolderFunc);
  644. ///
  645. /// FO_MoveFunc
  646. //  Asks user for the new destination
  647. SAVEDS void FO_MoveFunc(void)
  648. {
  649.    char path[SIZE_PATH];
  650.    GetMUIText(path, G->FO->GUI.TX_FPATH);
  651.    if (FO_FoldernameRequest(path)) set(G->FO->GUI.TX_FPATH, MUIA_Text_Contents, path);
  652. }
  653. MakeHook(FO_MoveHook, FO_MoveFunc);
  654. ///
  655. /// FO_CloseFunc
  656. //  Closes folder configuration window
  657. SAVEDS void FO_CloseFunc(void)
  658. {
  659.    DisposeModulePush(&G->FO);
  660. }
  661. MakeHook(FO_CloseHook, FO_CloseFunc);
  662. ///
  663. /// FO_SaveFunc
  664. //  Saves modified folder configuration
  665. SAVEDS void FO_SaveFunc(void)
  666. {
  667.    struct FO_GUIData *gui = &G->FO->GUI;
  668.    APTR lv = G->MA->GUI.NL_FOLDERS;
  669.    struct Folder folder, *oldfolder = G->FO->EditFolder;
  670.    BOOL success = FALSE;
  671.  
  672.    if (oldfolder)
  673.    {
  674.       memcpy(&folder, oldfolder, sizeof(struct Folder));
  675.       FO_PutFolder(&folder);
  676.       if (stricmp(oldfolder->Path, folder.Path))
  677.       {
  678.          if (Rename(oldfolder->Path, folder.Path)) strcpy(oldfolder->Path, folder.Path);
  679.          else
  680.             if (CreateDirectory(GetFolderDir(&folder))) if (FO_MoveFolderDir(&folder, oldfolder))
  681.                strcpy(oldfolder->Path, folder.Path);
  682.       }
  683.       strcpy(oldfolder->Name, folder.Name);
  684.       strcpy(oldfolder->MLAddress, folder.MLAddress);
  685.       strcpy(oldfolder->MLPattern, folder.MLPattern);
  686.       oldfolder->Sort[0] = folder.Sort[0];
  687.       oldfolder->Sort[1] = folder.Sort[1];
  688.       oldfolder->MaxAge  = folder.MaxAge;
  689.       if (!GetMUI(gui->CY_FTYPE, MUIA_Disabled))
  690.       {
  691.          int oldxpk = oldfolder->XPKType, newxpk = folder.XPKType;
  692.          BOOL changed = TRUE;
  693.          if (oldxpk == newxpk || (newxpk > 1 && !XpkBase)) changed = FALSE;
  694.          else if (!(newxpk&1) && (oldxpk&1) && oldfolder->LoadedMode != 2) changed = MA_PromptFolderPassword(&folder, gui->WI);
  695.          else if ((newxpk&1) && !(oldxpk&1)) changed = FO_EnterPassword(&folder);
  696.          if ((newxpk&1) && (oldxpk&1)) strcpy(folder.Password, oldfolder->Password);
  697.          if (changed)
  698.          {
  699.             if (!(newxpk&1)) *folder.Password = 0;
  700.             FO_XPKUpdateFolder(&folder, oldxpk);
  701.             oldfolder->XPKType = newxpk;
  702.             strcpy(oldfolder->Password, folder.Password);
  703.          }
  704.          oldfolder->Type = folder.Type;
  705.       }
  706.       set(gui->WI, MUIA_Window_Open, FALSE);
  707.       DoMethod(lv, MUIM_NList_Redraw, MUIV_NList_Redraw_All);
  708.       FO_SaveConfig(&folder);
  709.       success = TRUE;
  710.    }
  711.    else
  712.    {
  713.       clear(&folder, sizeof(struct Folder));
  714.       FO_PutFolder(&folder);
  715.       if (folder.XPKType&1) if (!FO_EnterPassword(&folder)) folder.XPKType &= ~1;
  716.       set(gui->WI, MUIA_Window_Open, FALSE);
  717.       if (CreateDirectory(GetFolderDir(&folder)))
  718.       {
  719.          int pos;
  720.          get(lv, MUIA_NList_Active, &pos);
  721.          DoMethod(lv, MUIM_NList_InsertSingle, &folder, ++pos);
  722.          FO_SaveConfig(&folder);
  723.          success = TRUE;
  724.       }
  725.    }
  726.    if (success)
  727.    {
  728.       MA_SetSortFlag();
  729.       DoMethod(G->MA->GUI.NL_MAILS, MUIM_NList_Sort);
  730.       MA_ChangeFolder(FO_GetFolderByName(folder.Name, NULL));
  731.       FO_SaveTree(CreateFilename(".folders"));
  732.    }
  733.    DisposeModulePush(&G->FO);
  734. }
  735. MakeHook(FO_SaveHook, FO_SaveFunc);
  736. ///
  737. /// FO_SetOrderFunc
  738. //  Saves or resets folder order
  739. SAVEDS ASM void FO_SetOrderFunc(REG(a1) int *arg)
  740. {
  741.    switch (*arg)
  742.    {
  743.       case SO_SAVE:  FO_SaveTree(CreateFilename(".folders")); break;
  744.       case SO_RESET: DoMethod(G->MA->GUI.NL_FOLDERS, MUIM_NList_Sort2, 10, 0); break;
  745.    }
  746. }
  747. MakeHook(FO_SetOrderHook, FO_SetOrderFunc);
  748. ///
  749.  
  750. /// FO_New
  751. //  Creates folder configuration window
  752. struct FO_ClassData *FO_New(void)
  753. {
  754.    struct FO_ClassData *data;
  755.  
  756.    if (data = calloc(1, sizeof(struct FO_ClassData)))
  757.    {
  758.       APTR bt_okay, bt_cancel;
  759.       static char *ftypes[4], *fmodes[5], *sortopt[8];
  760.       sortopt[0] = GetStr(MSG_FO_MessageDate);
  761.       sortopt[1] = GetStr(MSG_FO_DateRecvd);
  762.       sortopt[2] = GetStr(MSG_Sender);
  763.       sortopt[3] = GetStr(MSG_Recipient);
  764.       sortopt[4] = GetStr(MSG_Subject);
  765.       sortopt[5] = GetStr(MSG_Size);
  766.       sortopt[6] = GetStr(MSG_Status);
  767.       sortopt[7] = NULL;
  768.       fmodes[0]  = GetStr(MSG_FO_FMNormal);
  769.       fmodes[1]  = GetStr(MSG_FO_FMSimple);
  770.       fmodes[2]  = GetStr(MSG_FO_FMPack);
  771.       fmodes[3]  = GetStr(MSG_FO_FMEncPack);
  772.       fmodes[4]  = NULL;
  773.       ftypes[0]  = GetStr(MSG_FO_FTRcvdMail);
  774.       ftypes[1]  = GetStr(MSG_FO_FTSentMail);
  775.       ftypes[2]  = GetStr(MSG_FO_FTBothMail);
  776.       ftypes[3]  = NULL;
  777.       data->GUI.WI = WindowObject,
  778.          MUIA_Window_Title, GetStr(MSG_FO_EditFolder),
  779.          MUIA_HelpNode, "FO_W",
  780.          MUIA_Window_ID, MAKE_ID('F','O','L','D'),
  781.          WindowContents, VGroup,
  782.             Child, ColGroup(2), GroupFrameT(GetStr(MSG_FO_Properties)),
  783.                Child, Label2(GetStr(MSG_CO_Name)),
  784.                Child, data->GUI.ST_FNAME = MakeString(SIZE_NAME,GetStr(MSG_CO_Name)),
  785.                Child, Label2(GetStr(MSG_Path)),
  786.                Child, HGroup,
  787.                   MUIA_Group_HorizSpacing, 0,
  788.                   Child, data->GUI.TX_FPATH = TextObject, MUIA_Background, MUII_TextBack, MUIA_Frame, MUIV_Frame_Text, End,
  789.                   Child, data->GUI.BT_MOVE = PopButton(MUII_PopDrawer),
  790.                End,
  791.                Child, Label2(GetStr(MSG_FO_MaxAge)),
  792.                Child, data->GUI.ST_MAXAGE = MakeInteger(4,GetStr(MSG_FO_MaxAge)),
  793.                Child, Label1(GetStr(MSG_FO_FolderType)),
  794.                Child, data->GUI.CY_FTYPE = MakeCycle(ftypes,GetStr(MSG_FO_FolderType)),
  795.                Child, Label1(GetStr(MSG_FO_FolderMode)),
  796.                Child, data->GUI.CY_FMODE = MakeCycle(fmodes,GetStr(MSG_FO_FolderMode)),
  797.                Child, Label1(GetStr(MSG_FO_SortBy)),
  798.                Child, HGroup,
  799.                   Child, data->GUI.CY_SORT[0] = MakeCycle(sortopt,GetStr(MSG_FO_SortBy)),
  800.                   Child, data->GUI.CH_REVERSE[0] = MakeCheck(GetStr(MSG_FO_Reverse)),
  801.                   Child, LLabel1(GetStr(MSG_FO_Reverse)),
  802.                End,
  803.                Child, Label1(GetStr(MSG_FO_ThenBy)),
  804.                Child, HGroup,
  805.                   Child, data->GUI.CY_SORT[1] = MakeCycle(sortopt,GetStr(MSG_FO_ThenBy)),
  806.                   Child, data->GUI.CH_REVERSE[1] = MakeCheck(GetStr(MSG_FO_Reverse)),
  807.                   Child, LLabel1(GetStr(MSG_FO_Reverse)),
  808.                End,
  809.             End,
  810.             Child, ColGroup(2), GroupFrameT(GetStr(MSG_FO_MLSupport)),
  811.                Child, Label2(GetStr(MSG_FO_ToPattern)),
  812.                Child, data->GUI.ST_MLPATTERN = MakeString(SIZE_PATTERN,GetStr(MSG_FO_ToPattern)),
  813.                Child, Label2(GetStr(MSG_FO_ToAddress)),
  814.                Child, data->GUI.ST_MLADDRESS = MakeString(SIZE_ADDRESS,GetStr(MSG_FO_ToAddress)),
  815.             End,
  816.             Child, ColGroup(3),
  817.                Child, bt_okay = MakeButton(GetStr(MSG_Okay)),
  818.                Child, HSpace(0),
  819.                Child, bt_cancel = MakeButton(GetStr(MSG_Cancel)),
  820.             End,
  821.          End,
  822.       End;
  823.       if (data->GUI.WI)
  824.       {
  825.          DoMethod(G->App, OM_ADDMEMBER, data->GUI.WI);
  826.          SetHelp(data->GUI.ST_FNAME     ,MSG_HELP_FO_ST_FNAME     );
  827.          SetHelp(data->GUI.TX_FPATH     ,MSG_HELP_FO_TX_FPATH     );
  828.          SetHelp(data->GUI.ST_MAXAGE    ,MSG_HELP_FO_ST_MAXAGE    );
  829.          SetHelp(data->GUI.CY_FMODE     ,MSG_HELP_FO_CY_FMODE     );
  830.          SetHelp(data->GUI.CY_FTYPE     ,MSG_HELP_FO_CY_FTYPE     );
  831.          SetHelp(data->GUI.CY_SORT[0]   ,MSG_HELP_FO_CY_SORT0     );
  832.          SetHelp(data->GUI.CY_SORT[1]   ,MSG_HELP_FO_CY_SORT1     );
  833.          SetHelp(data->GUI.CH_REVERSE[0],MSG_HELP_FO_CH_REVERSE   );
  834.          SetHelp(data->GUI.CH_REVERSE[1],MSG_HELP_FO_CH_REVERSE   );
  835.          SetHelp(data->GUI.ST_MLPATTERN ,MSG_HELP_FO_ST_MLPATTERN );
  836.          SetHelp(data->GUI.ST_MLADDRESS ,MSG_HELP_FO_ST_MLADDRESS );
  837.          DoMethod(data->GUI.BT_MOVE  ,MUIM_Notify,MUIA_Pressed             ,FALSE         ,MUIV_Notify_Application,2,MUIM_CallHook,&FO_MoveHook);
  838.          DoMethod(bt_okay            ,MUIM_Notify,MUIA_Pressed             ,FALSE         ,MUIV_Notify_Application,2,MUIM_CallHook,&FO_SaveHook);
  839.          DoMethod(bt_cancel          ,MUIM_Notify,MUIA_Pressed             ,FALSE         ,MUIV_Notify_Application,2,MUIM_CallHook,&FO_CloseHook);
  840.          DoMethod(data->GUI.WI       ,MUIM_Notify,MUIA_Window_CloseRequest ,TRUE          ,MUIV_Notify_Application,2,MUIM_CallHook,&FO_CloseHook);
  841.          return data;
  842.       }
  843.       free(data);
  844.    }
  845.    return NULL;
  846. }
  847. ///
  848.  
  849.